/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月23日
 */
package com.massyframework.beanskin;

import java.nio.file.Path;

import org.slf4j.Logger;

import com.massyframework.beanskin.assembly.Assembly;
import com.massyframework.beanskin.fragment.Fragment;
import com.massyframework.beanskin.library.Library;
import com.massyframework.beanskin.license.License;
import com.massyframework.beanskin.license.LicenseChangedEvent;
import com.massyframework.beanskin.license.LicenseToExpireEvent;
import com.massyframework.beanskin.plugin.Plugin;
import com.massyframework.beanskin.service.adapt.Adaptable;
import com.massyframework.beanskin.util.classloading.ModuleClassLoader;

/**
 * 模块是系统中最小的可安装部署的功能组件或者单元, 它包括一组服务或者静态资源。
 * 
 * <p>
 * 在模块运行期间，系统为模块提供:
 * <ul>
 * <li>编号</li>
 * 编号在系统停止运行前保持不变。但不保正下次启动为模块分配相同的编号
 * <li>独立的类加载器</li>
 * 每个模块采用独立的类加载器，独立的类加载器将提供同一jar多版本支持的能力，也为模块静态资源的隔离性：
 * BEANSKIN-INF目录下的资源，不支持跨类加载器查询和加载。
 * <li>数据文件空间</li>
 * 系统为每个模块分配独立的数据文件空间，该空间下存放的文件在下次启动后依然有效。
 * <li>使用许可</li>
 * 提供由模块开发商签发的授权许可。
 * </ul>
 * 
 * <p>
 * 根据使用方式，beanskin framwork将模块划分为四类:
 * <ul>
 * <li>类库{@link Library}: 无方法入口的模块</li>
 * <li>插件{@link Plugin}: 提供基础设施的模块</li>
 * <li>装配件{@link Assembly}: 提供业务功能的模块</li>
 * <li>片段{@link Fragment}: 支持热拔插的模块</li>
 * </ul>
 * 
 * @author huangkh
 */
public interface Module<T extends ModuleConfig> extends 
	ModuleIdentifier, Adaptable{
	
	/**
	 * 添加事件监听器
	 * 
	 * @param listener {@link ModuleListener},监听器
	 */
	void addListener(ModuleListener listener);
		
	/**
	 * 模块的配置项
	 * @return {@link T}
	 */
	T getConfig();
	
	/**
	 * 按{@code name}获取数据文件
	 * 
	 * <p>
	 * 数据文件默认存放为运行工作空间的runtime/${组编号}/${模块编号}/${版本}目录。<br>
	 * 其中:<br> 
	 * ${组编号} = {@link Module#getGroupId()} <br>
	 * ${模块编号} = {@link Module#getModuleId()} <br>
	 * ${版本} = {@link Module#getVersion()}
	 * 
	 * @param name {@link String},相对文件名称
	 * @return {@link Path}
	 */
	Path getDataFile(String name);
	
	/**
	 * 编号
	 * <p>
	 * 由系统生成，按加载次序分配, 在jvm关闭前保持不变。
	 * 
	 * @return {@link int}
	 */
	int getId();
	
	/**
	 * 许可， 返回null时可按默认持有许可方式运行。
	 * <p>
	 * <ul>
	 * <li>社区版，许可默认返回null.</li>
	 * <li>企业版，当系统运行一段时间后（大约4小时)，系统才会核实模块的许可情况;</li>
	 * <i>
	 * 4小时时间，用于代码开发、调试以及系统功能演示所需时间。
	 * </i>
	 * </ul> 
	 * <p>
	 * 如果客户未获得许可，系统会发布{@link LicenseExpireEvent}事件，同时强制卸载模块;<br>
	 * 用户持有许可快到期时，会发布{@link LicenseToExpireEvent}；当更新许可后，会发布{@link LicenseChangedEvent}事件
	 * 
	 * @return {@link License}，可能返回null.
	 */
	License getLicense();
	

	/**
	 * 日志记录器
	 * @return {@link Logger}
	 */
	Logger getLogger();
	
	
	/**
	 * 模块类加载器
	 * @return {@link ModuleClassLoader}
	 */
	ModuleClassLoader getModuleClassLoader();
	
	/**
	 * 判断模块标识符是否等于{@code identifier}
	 * @param identifier {@link identifier},模块标识符
	 * @return {@link boolean}, 返回{@code true}表示等于，否则返回{@code false}
	 */
	boolean isModuleIdentifier(ModuleIdentifier identifier);
			
	/**
	 * 移除事件监听器
	 * @param listener {@link ModuleListener},监听器
	 */
	void removeListener(ModuleListener listener);
}
